#include "widget.h"
#include "./ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("服务器");
    udpsocket = new QUdpSocket(this);

    //一定要先链接信号，再绑定端口
    connect(udpsocket,&QUdpSocket::readyRead,this,&Widget::processRequest);


    bool ret =udpsocket->bind(QHostAddress::Any, 8888);
    if(!ret){
        QMessageBox::critical(nullptr, "服务器启动出错", udpsocket->errorString());
        return;
    }
}

Widget::~Widget()
{
    delete ui;
}

void Widget::processRequest()
{
    // 1. 读取请求（必须检查是否有数据且有效）
    if (!udpsocket->hasPendingDatagrams()) {
        qDebug() << "No pending datagrams";
        return;
    }

    QNetworkDatagram requestDatagram = udpsocket->receiveDatagram();
    if (!requestDatagram.isValid()) {
        qDebug() << "Invalid datagram received";
        return;
    }

    QByteArray requestData = requestDatagram.data();
    if (requestData.isEmpty()) {
        qDebug() << "Empty datagram data";
        return;
    }

    QString request = QString::fromUtf8(requestData);

    // 2. 根据请求计算响应
    QString response = process(request);  // 注意：不要返回const引用，避免悬垂引用

    // 3. 构造并发送响应数据报
    QNetworkDatagram responseDatagram;
    responseDatagram.setData(response.toUtf8());
    responseDatagram.setDestination(requestDatagram.senderAddress(),
                                    requestDatagram.senderPort());

    qint64 bytesSent = udpsocket->writeDatagram(responseDatagram);
    if (bytesSent == -1) {
        qDebug() << "Failed to send datagram:" << udpsocket->errorString();
    }

    // 4. 显示日志（线程安全方式）
    QString log = QString("[%1:%2] req: %3, resp: %4")
                      .arg(requestDatagram.senderAddress().toString())
                      .arg(requestDatagram.senderPort())
                      .arg(request)
                      .arg(response);

    // 如果跨线程调用，需要用信号槽
    QMetaObject::invokeMethod(ui->listWidget, [log, this]() {
        ui->listWidget->addItem(log);
    });
}

QString Widget::process(const QString& request)
{
    return request;
}
